import merge from 'lodash.merge';
import ReactDOM from 'react-dom';
// import {
//     TitleMarker,
//     TitleMarkerItem,
//     AreaName
// } from './TipMarker/TipMarker';
import 'echarts/lib/chart/lines';
import 'echarts/lib/chart/effectScatter';

class BaseMap {
  constructor(props) {
    // props 传入
    this.map = props.map;
    this.keywords = props.keywords;
    this.event = props.event || {};
    this.background = props.background || '';
    this.zoom = props.zoom || null;
    this.center = props.center || null;
    this.success = props.success || null;
    this.changeLoad = props.changeLoad || null;
    this.backgroundZoom = props.backgroundZoom || '';
    this.specialAreaConfigMap = props.specialAreaConfigMap || {};
    if (this.backgroundZoom) {
      var basic = 1920;
      var value = 0;
      if (document.body.offsetWidth - basic <= basic) {
        value = (document.body.offsetWidth - basic) / basic;
      }
      this.zoom = parseFloat(Number(this.backgroundZoom) + value).toFixed(4);
    }
    const defaultSubFeaturesOptions = {
      enable: true,
      cursor: 'default',
      bubble: true,
      strokeColor: 'rgba(9, 118, 227, 1)', //线颜色
      strokeOpacity: 1, //线透明度
      strokeWeight: 0.6, //线宽
      fillColor: 'rgba(9, 118, 227, 1)', //填充色
      fillOpacity: 0.1, //填充透明度
    };
    const defaultParentFeatureOptions = {
      enable: true,
      cursor: 'default',
      bubble: true,
      strokeColor: 'rgba(9, 118, 227, 1)', //线颜色
      fillColor: null,
      strokeWeight: 1, //线宽
    };
    const defaultNameMarkerStyle = {
      fillColor: 'rgba(9, 118, 227, 1)',
      fontSize: 14,
      fontWeight: '600',
      // strokeColor: '#fff',
      // strokeWidth: 2
    };
    this.active = merge(
      {
        enable: true,
        color: 'rgba(9, 118, 227, 1)',
        nameMarkerStyle: {
          ...defaultNameMarkerStyle,
          fillColor: '#ffffff',
        },
        subFeaturesOptions: {
          ...defaultSubFeaturesOptions,
          fillColor: 'rgba(9, 118, 227, 1)', //填充色
          fillOpacity: 1,
        },
        parentFeatureOptions: defaultParentFeatureOptions,
      },
      props.active,
    );
    this.hover = merge(
      {
        enable: true,
        subFeaturesOptions: {
          ...defaultSubFeaturesOptions,
          fillColor: 'rgba(9, 118, 227, 1)',
          fillOpacity: 0.7,
        },
        parentFeatureOptions: defaultParentFeatureOptions,
      },
      props.hover,
    );
    this.tipMarker = merge(
      {
        enable: false,
        layer: null,
        offset: [-130, -130],
      },
      props.tipMarker,
    );
    this.nameMarker = merge(
      {
        enable: true,
        style: defaultNameMarkerStyle,
      },
      props.nameMarker,
    );
    this.mapStatus = props.mapStatus || {
      dragEnable: false,
      zoomEnable: false,
      animateEnable: false,
    };
    this.districtExplorerOptions = props.districtExplorerOptions || {};
    this.subFeaturesOptions = merge(
      defaultSubFeaturesOptions,
      props.subFeaturesOptions,
    );
    this.parentFeatureOptions = merge(
      defaultParentFeatureOptions,
      props.parentFeatureOptions,
    );

    // 存储
    this.districtExplorer = null;
    this.id = null;
    this.areaNode = null;
    this.checkedAdcode = ''; // 选中的adcode
    this.markerContainer = null;
    this.layers = {};
    this.hierarchyData = {};
    this.nameMarkerList = {};
    this.isDestory = false;
    this.zoneCodeMap = {};
  }

  Layer = class Layer {
    constructor(props) {
      this.layer = props.layer;
      this.map = props.map;
    }
  };

  GaodeLayer = class GaodeLayer extends this.Layer {
    destory() {
      this.layer.setMap(null);
      this.map.remove(this.layer);
    }
  };

  // 初始化
  async install() {
    this.changeLoad && this.backgroundZoom && this.changeLoad(true);
    this.id = Math.random();
    this.mapStatus && this.setMapStatus();
    this.createDistrictExplorer();
    await this.createAreaNode();
    this.bindEvent();
    this.init && this.init();
  }

  complete() {
    this.changeLoad && this.backgroundZoom && this.changeLoad(false);
    this.success && this.success(this);
  }

  // 设置地图状态
  setMapStatus() {
    if (this.isDestory) {
      return;
    }
    this.map.setStatus(this.mapStatus);
  }

  // 创建行政实例
  createDistrictExplorer() {
    if (this.isDestory) {
      return;
    }
    this.districtExplorer = new window.AMapUI.DistrictExplorer(
      merge(
        {
          map: this.map,
          eventSupport: true,
          setAreaNodesForLocating: true,
        },
        this.districtExplorerOptions,
      ),
    );
  }

  // 创建当前行政节点
  createAreaNode() {
    return new Promise((reslove, reject) => {
      this.districtExplorer.loadAreaNode(this.keywords, (error, areaNode) => {
        if (error) {
          console.error(error);
          reject(error);
        }
        this.areaNode = areaNode;
        this.renderAreaNode();
        reslove();
        //绘制载入的区划节点
      });
    });
  }

  // 绘制当前行政节点
  renderAreaNode() {
    if (this.isDestory) {
      return;
    }
    //清除已有的绘制内容
    this.districtExplorer.clearFeaturePolygons();
    //绘制子级区划
    this.subFeaturesOptions.enable &&
      this.districtExplorer.renderSubFeatures(
        this.areaNode,
        this.subFeaturesOptions,
      );

    //绘制父级区划，仅用黑色描边
    this.parentFeatureOptions.enable &&
      this.districtExplorer.renderParentFeature(
        this.areaNode,
        this.parentFeatureOptions,
      );
    //更新地图视野以适合区划面
    if (this.center) {
      this.map.setCenter(this.center);
    } else if (this.subFeaturesOptions.enable) {
      this.map.setFitView(this.districtExplorer.getAllFeaturePolygons());
    }
    setTimeout(() => {
      let center = this.map.getCenter();
      if (this.background) {
        this.map.setZoomAndCenter(this.backgroundZoom, [
          center.lng,
          center.lat,
        ]);
        this.drawBackground();
        // this.complete();
      } else {
        this.zoom &&
          this.map.setZoomAndCenter(this.zoom, [center.lng, center.lat]);
        this.complete();
      }
    }, 300);
    this.tipMarker.enable && this.createTipMarker();
    this.nameMarker.enable && this.drawNameMarker();
  }

  getAreaProperties(adcode) {
    return this.specialAreaConfigMap[adcode] || {};
  }

  drawNameMarker() {
    if (this.isDestory) {
      return;
    }
    const geoData = this.areaNode._data.geoData;
    const subList = geoData.sub?.features;
    if (!subList) {
      return false;
    }
    var layer = new this.GaodeLayer({
      map: this.map,
      layer: new window.AMap.LabelsLayer({
        zooms: [3, 20],
        bubble: true,
        zIndex: 119,
      }),
    });
    subList.forEach((item) => {
      let props = {
        ...item.properties,
        ...this.getAreaProperties(item.properties.adcode),
      };
      var curData = {
        position: props.center,
        zIndex: 16,
        bubble: true,
        text: {
          direction: 'center',
          content: props.name,
          offset: [0, 0],
          style: this.nameMarker.style,
        },
      };
      var labelMarker = new window.AMap.LabelMarker(curData);
      this.nameMarkerList[props.adcode] = labelMarker;
      layer.layer.add(labelMarker);
    });
    this.map.add(layer.layer);
    this.layers['nameMarker'] = layer;
  }

  showNameMarker() {
    if (this.layers['nameMarker']) {
      this.layers['nameMarker'].layer.show();
    }
  }

  hideNameMarker() {
    if (this.layers['nameMarker']) {
      this.layers['nameMarker'].layer.hide();
    }
  }

  // 绘制层级图
  drawHierarchy(data) {
    if (!this.areaNode) {
      setTimeout(() => {
        this.drawHierarchy(data);
      }, 200);
      return false;
    }
    // 获取全部行政区域
    const allFeatures = this.areaNode.getSubFeatures();
    // 循环行政区域
    allFeatures.forEach((item) => {
      const adcode = item.properties.adcode;
      const polys = this.districtExplorer.findFeaturePolygonsByAdcode(adcode);
      for (let i = 0, len = polys.length; i < len; i++) {
        polys[i].setOptions(data[adcode] || this.subFeaturesOptions);
      }
    });
    this.hierarchyData = data;
  }

  // 绘制飞线图
  drawLine(option) {
    // const defaultOption = {
    // }
    // this.map.ae.setOption(merge({}, defaultOption, option));
  }

  // 绘制背景
  drawBackground() {
    if (this.isDestory) {
      return;
    }
    const containerWidth = this.map.K.offsetWidth;
    const containerHeight = this.map.K.offsetHeight;
    const imageSize = [this.background.width, this.background.height];
    const min = this.map.containerToLngLat(
      new window.AMap.Pixel(
        (-1 * (imageSize[0] - containerWidth)) / 2,
        containerHeight + (imageSize[1] - containerHeight) / 2,
      ),
    );
    const max = this.map.containerToLngLat(
      new window.AMap.Pixel(
        containerWidth + (imageSize[0] - containerWidth) / 2,
        (-1 * (imageSize[1] - containerHeight)) / 2,
      ),
    );
    const minLngLat = new window.AMap.LngLat(min.lng, min.lat);
    const maxLngLat = new window.AMap.LngLat(max.lng, max.lat);
    const bounds = new window.AMap.Bounds(minLngLat, maxLngLat);
    const imageLayer = new window.AMap.ImageLayer({
      bounds,
      url: this.background.url,
      zIndex: 15,
      opacity: 1,
      zooms: [this.zoom],
    });
    this.map.add(imageLayer);
    let center = this.map.getCenter();
    this.map.setZoomAndCenter(this.zoom, [center.lng, center.lat]);
    this.layers['backgroundLayer'] = new this.GaodeLayer({
      map: this.map,
      layer: imageLayer,
    });
    this.complete();
  }

  bindEvent() {
    if (this.isDestory) {
      return;
    }
    this.districtExplorer.setAreaNodesForLocating([this.areaNode]);
    this.districtExplorer.on('featureClick', (e, feature) => {
      feature.properties = {
        ...feature.properties,
        ...this.getAreaProperties(feature.properties.adcode),
      };
      this.baseFeatureClick && this.baseFeatureClick(e, feature);
      this.featureClick && this.featureClick(e, feature);
      this.event.featureClick && this.event.featureClick(e, feature);
    });
    this.districtExplorer.on('featureMouseover', (e, feature) => {
      feature.properties = {
        ...feature.properties,
        ...this.getAreaProperties(feature.properties.adcode),
      };
      this.baseFeatureMouseover && this.baseFeatureMouseover(e, feature);
      this.featureMouseover && this.featureMouseover(e, feature);
      this.event.featureMouseover && this.event.featureMouseover(e, feature);
    });
    this.districtExplorer.on('featureMouseout', (e, feature) => {
      feature.properties = {
        ...feature.properties,
        ...this.getAreaProperties(feature.properties.adcode),
      };
      this.baseFeatureMouseout && this.baseFeatureMouseout(e, feature);
      this.featureMouseout && this.featureMouseout(e, feature);
      this.event.featureMouseout && this.event.featureMouseout(e, feature);
    });
    this.districtExplorer.on('featureMousemove', (e, feature) => {
      feature.properties = {
        ...feature.properties,
        ...this.getAreaProperties(feature.properties.adcode),
      };
      this.baseFeatureMousemove && this.baseFeatureMousemove(e, feature);
      this.featureMousemove && this.featureMousemove(e, feature);
      this.event.featureMousemove && this.event.featureMousemove(e, feature);
    });
    this.districtExplorer.on('outsideClick', (e, feature) => {
      if (feature) {
        feature.properties = {
          ...feature.properties,
          ...this.getAreaProperties(feature.properties.adcode),
        };
      }
      this.baseFeatureoutsideClick && this.baseFeatureoutsideClick(e, feature);
      this.outsideClick && this.outsideClick(e, feature);
      this.event.outsideClick && this.event.outsideClick(e, feature);
    });
  }

  createTipMarker() {
    if (this.isDestory) {
      return;
    }
    let markerContainer = document.createElement('div');
    this.markerContainer = markerContainer;
    let marker = new this.GaodeLayer({
      map: this.map,
      layer: new window.AMap.Marker({
        content: markerContainer,
        anchor: 'bottom',
        // offset: new window.AMap.Pixel(this.tipMarker.offset[0], this.tipMarker.offset[1]),
        bubble: true,
        zIndex: 10,
      }),
    });
    this.layers['tipMarker'] = marker;
  }

  toggleHoverFeature(feature, isHover, position) {
    if (!feature) {
      return;
    }
    const props = feature.properties;
    if (this.tipMarker.enable) {
      if (isHover) {
        let offset = null;
        // 更新位置
        this.layers['tipMarker'].layer.setPosition(position || props.center);
        // 更新偏移
        if (this.tipMarker.offset instanceof Function) {
          let offsetResult = this.tipMarker.offset(props);
          offset = new window.AMap.Pixel(offsetResult[0], offsetResult[1]);
        } else if (this.tipMarker.offset instanceof Array) {
          offset = new window.AMap.Pixel(
            this.tipMarker.offset[0],
            this.tipMarker.offset[1],
          );
        }
        this.layers['tipMarker'].layer.setOffset(offset);
        // this.layers['tipMarker'].layer.setOffset(position || props.center);
        if (this.markerContainer) {
          const markerContent = this.tipMarker.formatter
            ? this.tipMarker.formatter(props)
            : '空';
          ReactDOM.render(markerContent, this.markerContainer);
        }
        this.layers['tipMarker'].layer.setMap(this.map);
      } else {
        this.layers['tipMarker'].layer.setMap(null);
      }
    }
    if (props.adcode === this.checkedAdcode) {
      return false;
    }
    //更新相关多边形的样式
    const polys = this.districtExplorer.findFeaturePolygonsByAdcode(
      props.adcode,
    );
    for (let i = 0, len = polys.length; i < len; i++) {
      if (this.hover.enable) {
        if (isHover) {
          polys[i].setOptions(this.hover.subFeaturesOptions);
        } else {
          polys[i].setOptions(
            this.hierarchyData[props.adcode] || this.subFeaturesOptions,
          );
        }
      }
    }
  }

  checkedArea(feature) {
    const props = feature.properties;
    const allFeatures = this.areaNode.getSubFeatures();
    this.checkedAdcode = props.adcode;
    allFeatures.forEach((item) => {
      const adcode = item.properties.adcode;
      const polys = this.districtExplorer.findFeaturePolygonsByAdcode(adcode);
      for (let i = 0, len = polys.length; i < len; i++) {
        polys[i].setOptions(
          adcode === this.checkedAdcode
            ? this.active.subFeaturesOptions
            : this.hierarchyData[adcode] || this.subFeaturesOptions,
        );
      }
      // 这里需要重写
      if (this.nameMarker.enable) {
        if (adcode === this.checkedAdcode) {
          const nameMarker = this.nameMarkerList[adcode];
          nameMarker.setText({
            style: this.active.nameMarkerStyle,
          });
        } else {
          this.nameMarkerList[adcode].setText({
            style: this.nameMarker.style,
          });
        }
      }
    });
  }

  removeChecked() {
    const allFeatures = this.areaNode.getSubFeatures();
    allFeatures.forEach((item) => {
      const adcode = item.properties.adcode;
      if (adcode === this.checkedAdcode) {
        const polys = this.districtExplorer.findFeaturePolygonsByAdcode(adcode);
        for (let i = 0, len = polys.length; i < len; i++) {
          polys[i].setOptions(
            this.hierarchyData[adcode] || this.subFeaturesOptions,
          );
        }
      }
      // 这里需要重写
      if (this.nameMarker.enable) {
        if (adcode === this.checkedAdcode) {
          this.nameMarkerList[adcode].setText({
            style: this.nameMarker.style,
          });
        }
      }
    });
    this.checkedAdcode = '';
  }

  baseFeatureClick(e, feature) {
    this.active.enable && this.checkedArea(feature);
  }

  baseFeatureMouseover(e, feature) {
    this.toggleHoverFeature(
      feature,
      e.type === 'featureMouseover',
      e.originalEvent ? e.originalEvent.lnglat : null,
    );
  }

  baseFeatureMouseout(e, feature) {
    this.toggleHoverFeature(
      feature,
      e.type === 'featureMouseover',
      e.originalEvent ? e.originalEvent.lnglat : null,
    );
  }

  baseFeatureMousemove(e, feature) {
    this.tipMarker.enable &&
      this.layers['tipMarker'].layer.setPosition(e.originalEvent.lnglat);
  }

  baseFeatureoutsideClick(e, feature) {
    this.active.enable && this.removeChecked();
  }

  clearLayers(layers) {
    for (let key in layers) {
      let item = layers[key];
      if (item instanceof this.Layer) {
        item.destory();
      } else {
        this.clearLayers(item);
      }
    }
  }

  uninstall() {
    this.isDestory = true;
    // 清除
    if (this.districtExplorer) {
      this.districtExplorer.clearFeaturePolygons();
      this.districtExplorer.clearAreaNodeCache();
      this.districtExplorer.destroy();
      this.districtExplorer = null;
    }
    // 清除areaNode
    this.areaNode = null;
    // 清除layers
    this.clearLayers(this.layers);
    this.layers = {};

    // 清除飞线图
    this.map.ae.setOption({
      series: [
        {
          type: 'effectScatter',
          coordinateSystem: 'amap',
          data: [],
        },
        {
          type: 'lines',
          coordinateSystem: 'amap',
          data: [],
        },
      ],
    });
    document.querySelectorAll('.amap-custom canvas').forEach((c) => {
      let cxt = c.getContext('2d');
      cxt.clearRect(0, 0, c.width, c.height);
    });
    this.destory && this.destory();
    this.event.destory && this.event.destory();
  }
}

export default BaseMap;
